package org.javahispano.javacup.tacticas_aceptadas.gorkag.init;

import org.javahispano.javacup.modelo.*;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class TacticaInit implements Tactica {

    Posicion alineacion1[]=new Posicion[]{
            new Posicion(0.0,-50.124434389140276),
            new Posicion(-9.272727272727272,-31.59502262443439),
            new Posicion(13.076923076923078,-31.59502262443439),
            new Posicion(26.391608391608393,-23.993212669683256),
            new Posicion(-23.776223776223777,-23.755656108597286),
            new Posicion(11.888111888111888,-12.115384615384617),
            new Posicion(-8.55944055944056,-11.402714932126697),
            new Posicion(25.916083916083913,8.789592760180994),
            new Posicion(-24.965034965034967,8.552036199095022),
            new Posicion(-0.951048951048951,14.96606334841629),
            new Posicion(-0.951048951048951,31.83257918552036)
        };

        Posicion alineacion2[]=new Posicion[]{
            new Posicion(0.2595419847328244,-50.41044776119403),
            new Posicion(-11.16030534351145,-31.082089552238806),
            new Posicion(11.16030534351145,-31.6044776119403),
            new Posicion(27.251908396946565,-27.94776119402985),
            new Posicion(-29.84732824427481,-26.902985074626866),
            new Posicion(8.564885496183205,-7.574626865671642),
            new Posicion(-10.641221374045802,-7.052238805970149),
            new Posicion(27.251908396946565,4.440298507462686),
            new Posicion(-28.76923076923077,3.3257918552036196),
            new Posicion(-0.2595419847328244,19.067164179104477),
            new Posicion(-0.2595419847328244,35.78358208955224)
        };

        Posicion alineacion3[]=new Posicion[]{
            new Posicion(0.2595419847328244,-50.41044776119403),
            new Posicion(-11.16030534351145,-31.082089552238806),
            new Posicion(11.16030534351145,-31.6044776119403),
            new Posicion(26.732824427480914,-20.111940298507463),
            new Posicion(-29.32824427480916,-21.67910447761194),
            new Posicion(0.2595419847328244,-0.26119402985074625),
            new Posicion(-18.946564885496183,-0.26119402985074625),
            new Posicion(18.946564885496183,-0.26119402985074625),
            new Posicion(-18.78321678321678,35.39592760180996),
            new Posicion(-0.2595419847328244,19.067164179104477),
            new Posicion(18.946564885496183,35.26119402985075)
        };

        Posicion alineacion4[]=new Posicion[]{
            new Posicion(0.2595419847328244,-50.41044776119403),
            new Posicion(-18.307692307692307,-30.88235294117647),
            new Posicion(0.0,-31.59502262443439),
            new Posicion(19.020979020979023,-30.6447963800905),
            new Posicion(-0.23776223776223776,-14.490950226244346),
            new Posicion(11.16030534351145,-1.3059701492537314),
            new Posicion(-10.641221374045802,-0.7835820895522387),
            new Posicion(25.202797202797203,18.054298642533936),
            new Posicion(-21.636363636363637,18.29185520361991),
            new Posicion(8.55944055944056,31.357466063348415),
            new Posicion(-7.37062937062937,31.59502262443439)
        };

        Posicion alineacion5[]=new Posicion[]{
            new Posicion(0.2595419847328244,-50.41044776119403),
            new Posicion(-11.16030534351145,-35.78358208955224),
            new Posicion(12.717557251908397,-35.26119402985075),
            new Posicion(28.290076335877863,-28.470149253731343),
            new Posicion(-28.290076335877863,-28.470149253731343),
            new Posicion(14.793893129770993,-18.544776119402986),
            new Posicion(-11.888111888111888,-18.29185520361991),
            new Posicion(21.3986013986014,-4.751131221719457),
            new Posicion(-23.062937062937063,-4.751131221719457),
            new Posicion(0.4755244755244755,-6.414027149321266),
            new Posicion(0.0,0.0)
        };

        Posicion alineacion6[]=new Posicion[]{
            new Posicion(0.2595419847328244,-50.41044776119403),
            new Posicion(-11.16030534351145,-35.78358208955224),
            new Posicion(12.717557251908397,-35.26119402985075),
            new Posicion(28.290076335877863,-28.470149253731343),
            new Posicion(-28.290076335877863,-28.470149253731343),
            new Posicion(6.6573426573426575,-18.766968325791854),
            new Posicion(-7.132867132867133,-18.29185520361991),
            new Posicion(21.874125874125873,-4.038461538461538),
            new Posicion(-24.013986013986013,-4.038461538461538),
            new Posicion(-6.4885496183206115,-6.529850746268657),
            new Posicion(9.272727272727272,0.0)
        };

    public Posicion[] getPosicionSaca(SituacionPartido sp) {
    return alineacion5;
    }

    public Posicion[] getPosicionRecive(SituacionPartido sp) {
    return alineacion6;
    }

    private TacticaDetalleInit detalle = new TacticaDetalleInit();
    
    public TacticaDetalle getDetalle() {
        return detalle;
    }
    
    LinkedList<Comando> comandos = new LinkedList<Comando>();
    
    private Posicion[] alineacionEnCurso;
    
    private Random rand = new Random();
    
    private int[] rivalesCubiertos =
    	new int[]{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,};
    
    //private int jugadorTrasBalon = -1;
    
    private boolean tengoYoElBalon = false;

    public List<Comando> ejecutar(SituacionPartido sp) {
    	//vaciamos las vbles globales
        comandos.clear();
        //jugadorTrasBalon = -1;
        
        ////System.out.println("Estoy????");
        
        alineacionEnCurso = alineacion2; // cual es la que se parece a la 1 ??? para ponerla en el saque, cambia 8, 9,10,11
        
        for (int i = 1;i<11;i++){
        	comandos.add(new ComandoIrA(i, alineacionEnCurso[i]));
        }
        
        comandos.addAll(getComandosPortero(sp));
        
        /* IDEAS:
        - extremos suban lo que quieran
        - si balon en campo contrario toda alineacion arriba un poco
        - media, si hay alguien cerca (a menos de 2*te la quita) pase m�s largo
        - puede valer de lo de la distancia = angulo para pases?
        - pases adelantados? cuanto?
        - DEFENSAS:
        - carrileros?
        - primero ver adversarios cercanos y cubrirlos para que no reciban (en la linea de pase, pero cerca de los delanteros)
        - Empezar en orden, un central marcador, otro libero, si sobran, suben carrileros
        - estos cambios, que sean por cambio de alineacion! mooola! no es cambio de sistema, es sistema en ataque, defensa, contra ataque de 2, de 3, etc
        
        */
    	
       /*Posicion[] defensas = sp.misJugadores();
    	for(//Posicion medio: sp.misJugadores()
    		int j = 1; j < 5 ; j++
    		){
    		Posicion defensa = defensas[j];
    		
    		// los cuatro defensas cubren a los cuatro mas adelantados del rival
    		/*
    		int[] rivales = Constantes.centroArcoInf
    			.indicesMasCercanos(sp.rivales()
    					,rivalesCubiertos);
    		
    		for(int k = 0; k < rivales.length | k < 4; k++){
    			comandos.add(
    				new ComandoIrA(j,
    					sp.rivales()[k]
    						.moverPosicion(0,
    								sp.rivales()[k].getY()>0?-5:5
    						)
    					)
    				);
    			rivalesCubiertos[j] = rivales[k];
    			}*
    		
    		}*/
        
        comandos.addAll(getComandosDefensa(sp));
        
    	//comandos.addAll(getComandosMedia(sp));
    	
    	Posicion[] delanteros = sp.misJugadores();
    	for(int i = 9; i < 11; i++){
    		Posicion delantero = delanteros[i];
    		if(
    				delantero.distancia(alineacionEnCurso[i]) < 20 &&
    				delantero.distancia(sp.balon())<20){
    			comandos.add(
    				new ComandoIrA(
    					i,
    					sp.balon()
    				)
    			);
    		}else{
    			comandos.add(
        				new ComandoIrA(
        					i,
        					alineacionEnCurso[i]
        				)
        			);
    		}
    	}
    	
    	/*if(sp.sacaRival()){
    		//System.out.println(sp.balon().distancia());
    		if( sp.balon().distancia() < 5)//sacan de centro, el anterior tiro fue gol
    			//System.out.println("ANTERIOR TIRO FUE GOL!");
    		else
    			//System.out.println("fallo en el tiro anterior!");
    	}*/
    	
    	// remates a puerta / pases
    	int rematan[] = sp.puedenRematar();
    	for(int rematador : rematan){
    		//boolean pase = false;
    		/*int[] cercanos = sp.misJugadores()[i].indicesMasCercanos(sp.misJugadores());
    		for (int j = 1; !pase && j < cercanos.length; j++) {
    			//System.out.println("pase a:" + j);
        		//System.out.println("pase a:" + sp.detalleMisJugadores()[j].getNumero());
    			comandos.add(new ComandoGolpearBalon(i, sp.misJugadores()[cercanos[j]], 1, true));
    			pase = true;
    		}*/
    		if (rematador == 0) continue; // el portero va aparte
    		
    		Posicion rem = sp.misJugadores()[rematador]; 
    		
    		//if(rem.distancia(Constantes.centroArcoSup)<15){ 
    			//TODO calcular el angulo para que, tirando a 1 de fuerza,
    			// el tiro llegue a mas altura que 
    			//Constantes.ALTURA_CONTROL_BALON_PORTERO
    			// y menos que
    			//Constantes.ALTO_ARCO
    			//a la linea de gol
    			// ANGULO DE MAXIMA LLEGADA --> 45�
    			double distanciaPorteria = rem.distancia(Constantes.centroArcoSup);
    			if(distanciaPorteria<30
    					&& distanciaPorteria >15){
    				double anguloTiro = calcularAnguloTiro(rem.distancia(Constantes.centroArcoSup));
    					//distanciaPorteria;//rem.distancia(Constantes.centroArcoSup);
    				double dispararA = 
    					Constantes.LARGO_ARCO/4*(rand.nextBoolean()?1:-1);
    				double desviacionPosible = calcularPosicionTiro(rem, sp.detalleMisJugadores()[rematador].getPresicion());
	    			
    				/*comandos.add(new ComandoGolpearBalon(rematador,
	    					Constantes.centroArcoSup.moverPosicion(desviacionPosible,0)
	    					//desviacionPosible
	    					//180 + rem.angulo(Constantes.centroArcoSup.moverPosicion(dispararA,0))*180/Math.PI
	    					//(rem.angulo(Constantes.centroArcoSup)*180/Math.PI) + desviacionPosible
	    					,1,
	    					anguloTiro));*/
	    			addComandoGolpeo(comandos, new ComandoGolpearBalon(rematador,
	    					Constantes.centroArcoSup.moverPosicion(desviacionPosible,0)
	    					//desviacionPosible
	    					//180 + rem.angulo(Constantes.centroArcoSup.moverPosicion(dispararA,0))*180/Math.PI
	    					//(rem.angulo(Constantes.centroArcoSup)*180/Math.PI) + desviacionPosible
	    					,1,
	    					anguloTiro));
	    			
	    			////System.out.println("Inf: " + 180*rem.angulo(Constantes.centroArcoInf)/Math.PI);
	    			////System.out.println("Sup: " + 180*rem.angulo(Constantes.centroArcoSup)/Math.PI);
	    			/*//System.out.println("Voy a tirar, con angulo "
	    					+ anguloTiro
	    					+ " desde distancia "
	    					+ rem.distancia(Constantes.centroArcoSup)
	    					);*/
	    			
	    			
	    			//TODO OJO! el angulo no hace como la posicion, que centroArcoSup es donde atacas!
	    			/*//System.out.println("Tirar�a como: "
	    					+ Constantes.centroArcoSup
	    					+ " angulo " + rem.angulo(Constantes.centroArcoSup)
	    					+ " tiro realmente a " + rem.angulo(Constantes.centroArcoSup)*180/Math.PI
	    					+ " cons desviacion " + desviacionPosible
	    					//+ rem.angulo(Constantes.centroArcoSup)
	    					//+ " desviacion: " + desviacionPosible
	    					//+ " pero el 'bueno' es " + (180 + rem.angulo(Constantes.centroArcoSup.moverPosicion(dispararA,0))*180/Math.PI)
	    					);*/
	    			
	    			////System.out.println("LECHE! " + + "");
    			}
    			// INTENTA REGATEAR!
    			else if (distanciaPorteria <= 15
    					){
    				//TODO ESTO ESTA SIN PROBAR!!!
    				//(x -x0)^2 + (y - y0)^2 = R
    				
    				// Calcular el angulo de ti con el centro de la porteria
    				// y del portero rival con el centro de la porteria
    				// si mayor de 15� entonces TIRA!!!
    				double anguloTuyo =
    					rem.angulo(Constantes.centroArcoSup);
    				double anguloPortero =
    					sp.rivales()[0].angulo(Constantes.centroArcoSup);
    				
    				double anguloTotal =
    					Math.abs(anguloTuyo - anguloPortero);
    				
    				////System.out.println(anguloTotal+" "+Math.PI/9);
    				
    				if (anguloTotal > Math.PI/9){
    					/*comandos.add(new ComandoGolpearBalon(rematador,
    	    					Constantes.centroArcoSup
    	    						.moverPosicion(
    	    								0,//Constantes.LARGO_ARCO/4*(rand.nextBoolean()?1:-1),
    	    								0)
    	    								,1,
    	    								false));*/
    					addComandoGolpeo(comandos, new ComandoGolpearBalon(rematador,
    	    					Constantes.centroArcoSup
	    						.moverPosicion(
	    								0,//Constantes.LARGO_ARCO/4*(rand.nextBoolean()?1:-1),
	    								0)
	    								,1,
	    								false));
    				}else{
    					/*comandos.add(new ComandoGolpearBalon(rematador,
    	    					rem.moverPosicion(-5, 0)
    	    								,0.3,
    	    								false));*/
    					addComandoGolpeo(comandos, new ComandoGolpearBalon(rematador,
    	    					rem.moverPosicion(-5, 0)
								,0.3,
								false));
    				}
    		}
    		else{
    			if(rematador == 10 ||
    					rematador == 9){ // Acercate...
    				/*comandos.add(new ComandoGolpearBalon(rematador,
    						Constantes.centroArcoSup,
	    					0.4
	    					, false));*/
    				addComandoGolpeo(comandos, new ComandoGolpearBalon(rematador,
    						Constantes.centroArcoSup,
	    					0.4
	    					, false));
    			}
    			else{
    				//sp.detalleMisJugadores()[rematador].getRemate();
    				//Constantes.getVelocidadRemate(sp.detalleMisJugadores()[rematador].getRemate());
	    			
	    			
	    			// Patadon al delantero!!!
	    			// mejor:
	    			//		1.- Pase al m�s adelantado que no tenga un rival en trayectoria
	    			//		2.- Si no lo hay, entonces al m�s abierto a la banda (buscar huecos)
	    			//		3.- Si no lo hay tampoco (eres el mas cercano a la banda),
	    			//			entonces, hacia atr�s al que no tenga rival en trayectoria
	    			
    				Comando com = getMejorPase(rematador, rem, sp);
    				if (com == null)
    					com = new ComandoGolpearBalon(rematador,
    	    					Posicion.media(
    	    							//sp.misJugadores()[rem.indiceMasCercano(sp.misJugadores())],
    	    							sp.misJugadores()[10],
    	    							Constantes.centroArcoSup),
    	    					rem.distancia(sp.misJugadores()[10])<20?0.5:1
    	    					//0.5//rem.distancia(alineacionEnCurso[10])
    	    					///Constantes.getVelocidadRemate(sp.detalleMisJugadores()[rematador].getRemate())
    	    					, true);
	    			//comandos.add(com);
    				addComandoGolpeo(comandos, com);
	    			
    			}
    			
    			// El delantero que vaya a buscarla a su punto (o le llega, o le llegara...)
    			comandos.add(new ComandoIrA(10, alineacionEnCurso[10]));
    		}
    			
		if(sp.saco()){
			// si es saque (de banda), manda esto, patadon al delantero... si estoy al otro lado del centro...
			if(Constantes.centroArcoSup.distancia(rem)> Constantes.centroArcoInf.distancia(rem)){
				/*comandos.add(new ComandoGolpearBalon(rematador,
					alineacionEnCurso[10],
					1
					, true));*/
				addComandoGolpeo(comandos, new ComandoGolpearBalon(rematador,
						alineacionEnCurso[10],
						1
						, true));
			}else{
				// si estoy en mi campo, entonces al m�s cercano...
				/*comandos.add(new ComandoGolpearBalon(rematador,
						sp.balon().indiceMasCercano(
		    					sp.misJugadores()
		    				),
						0.5 //TODO aqui hay que controlar la fuerza de media...
						, false));*/
				addComandoGolpeo(comandos, new ComandoGolpearBalon(rematador,
						sp.balon().indiceMasCercano(
		    					sp.misJugadores()
		    				),
						0.5 //TODO aqui hay que controlar la fuerza de media...
						, false));
			}
	    	// si tengo que sacar, entonces que se acerque al balon el que este mas cerca			
			comandos.add(
	    			new ComandoIrA(
	    				sp.balon().indiceMasCercano(
	    					sp.misJugadores()
	    				),
	    				sp.balon()
	    			)
	    		);
			
			// El delantero que vaya a buscarla a su punto (o le llega, o le llegara...)
			comandos.add(new ComandoIrA(10, alineacionEnCurso[10]));
			}
    		
    	}
    	
    	return comandos;
    }
    
    private Comando getMejorPase(int rematador, Posicion rem, SituacionPartido sp) {
    	
    	Comando resultado = null;
    	double diferencia = 0.0;
    	//System.out.println("Buscando pase de " + rematador);
    	
    	for(Posicion pasable : sp.misJugadores()){
			if (pasable != rem){
				// busco si le puedo dar pase adelantado a alguien
				/*System.out.println("Buscando pase adelantado a " + 
						pasable.getY()+
						" desde " + rem.getY()+
						" con diferencia " + (pasable.getY()
								- rem.getY()) +
						" con referencia " + diferencia);*/
				if(pasable.getY()
						- rem.getY()
						> diferencia){
					// potencial pase, a ver si no hay rivales en la trayectoria
					if(!hayRivalesEnTrayectoria(rem, pasable, sp.rivales())){
						diferencia = pasable.getY() - rem.getY();
						resultado = new ComandoGolpearBalon(rematador,
	    					pasable,
	    					//rem.distancia(pasable)<20?0.5:1
	    					calcularFuerzaLineal(rem.distancia(pasable))
	    					, true);
					}
				}
			}
		}
    	
    	if (resultado == null){
    		diferencia = 0;
    		for(Posicion pasable : sp.misJugadores()){
    			if (pasable != rem){
    				// busco si le puedo dar pase adelantado a alguien
    				/*System.out.println("Buscando pase abierto y adelantado a " + 
    						pasable.getX()+
    						" desde X" + rem.getX()+
    						" con diferencia " + Math.abs(pasable.getX()
    								- rem.getX()) +
    						" con referencia " + diferencia +
    						" y diferencia de Y " + (pasable.getY()>rem.getY()));*/
    				if(Math.abs(pasable.getX()-rem.getX())
    						> diferencia
    						&& pasable.getY()>rem.getY()){
    					// potencial pase, a ver si no hay rivales en la trayectoria
    					if(!hayRivalesEnTrayectoria(rem, pasable, sp.rivales())){
    						diferencia = Math.abs(pasable.getX()-rem.getX());
    						resultado = new ComandoGolpearBalon(rematador,
    	    					pasable,
    	    					//rem.distancia(pasable)<20?0.5:1
    	    					calcularFuerzaLineal(rem.distancia(pasable))
    	    					, true);
    					}
    				}
    			}
    		}
    	}
    	
    	
    	if (resultado == null){
    		diferencia = 0;
    		for(Posicion pasable : sp.misJugadores()){
    			if (pasable != rem){
    				// busco si le puedo dar pase a alguien
					// potencial pase, a ver si no hay rivales en la trayectoria
    				//System.out.println("Buscando pase a donde sea");
    				if(!hayRivalesEnTrayectoria(rem, pasable, sp.rivales()))
    					resultado = new ComandoGolpearBalon(rematador,
	    					pasable,
	    					//rem.distancia(pasable)<20?0.5:1
	    					calcularFuerzaLineal(rem.distancia(pasable))
	    					, true);
				}
			}
		}
    	
    	/*// para aquellos que no son el rematador...
		if(pasable != getPaseAdelantado(rem, pasable)){
			
		}else if (pasable != getPaseBanda(rem, pasable)){
			
		}else{
			getPaseAtras(rem, pasable);
		}*/
    	
    	//System.out.println("PASE! " + resultado);
    	return resultado;
	}

	private boolean hayRivalesEnTrayectoria(Posicion rem, Posicion pasable,
			Posicion[] rivales) {
		// repaso cada rival y miro si el angulo entre el rematador y el pasable
		// y el rematador y el rival es mayor que 20�?
		
		boolean resultado = false;
		double miAngulo = rem.angulo(pasable);
		double LIMITE = 0.35;
		
		//System.out.println("Mi angulo es: " + miAngulo);
		//System.out.println("Mi referencia es: " + LIMITE);
		
		for(Posicion rival : rivales){
			//System.out.println("\tComparando con : " + Math.abs(miAngulo - rem.angulo(rival)));
			if (Math.abs(miAngulo - rem.angulo(rival))<(LIMITE)){
				// hay uno, si encima esta mas cerca, malo!
				if(rem.distancia(pasable)> rem.distancia(rival)){
					resultado = true;
					break;
					}
				}
		}
		
		return resultado;
	}

	private List<Comando> getComandosDefensa(SituacionPartido sp){
    	List<Comando> comandosDefensa = new LinkedList<Comando>(); 
    	
    	//JugadorDetalle detalleMedio10 = sp.detalleMisJugadores()[0];
    	//while((detalleMedio10 = sp.detalleMisJugadores()[i++]).getNumero()!=10);
    	//Posicion medio10 = sp.misJugadores()[--i]; // en i queda el indice del jugador
    	Posicion[] defensas = sp.misJugadores();
    	int masCercano = sp.balon().indiceMasCercano(sp.misJugadores());
    	
    	for(//Posicion medio: sp.misJugadores()
    		int j = 1; j < 9//5
    			; j++
    		){
    		Posicion defensa = defensas[j];
		    // si estas a menos de 15 del balon,
    		// ve a por el, pero solo hasta X de distancia de tu sitio
    		if(
    				//jugadorTrasBalon != -1 &&
    				j == masCercano
    				//&& defensa.distancia(sp.balon())<15
		    		//&& defensa.distancia(alineacionEnCurso[j]) <= 30	
		    		){
    				comandosDefensa.add(new ComandoIrA(j, sp.balon()));
    				rivalesCubiertos[j]=-1;
		    		//jugadorTrasBalon = j;
		    	}
		    	// si no, vuelve a tu sitio --> mejor, a marcar a alg�n medio
    		/*else if(defensa.distancia(alineacionEnCurso[j]) > 30){
    			comandosDefensa.add(new ComandoIrA(j,
		    				alineacionEnCurso[j]
		    				));
    			rivalesCubiertos[j]=-1;
		    }*/
    		else{
    			
        		if(!tengoYoElBalon){
        			// si no, vuelve a tu sitio --> mejor, a marcar a alg�n medio
		    		if(rivalesCubiertos[j]==-1){
			    		int rivalACubrir = alineacionEnCurso[j]
			    		        .indiceMasCercano(sp.rivales(),
			    		        		rivalesCubiertos);
			    		comandosDefensa.add(new ComandoIrA(j,
			    				//alineacionEnCurso[j]
			    				// para la defensa no vale el punto medio, demasiado lejos en ataque
			    				Posicion.media(
			    						sp.rivales()[rivalACubrir]
			    						,sp.balon()
			    						)
			    				)
			    		);
			    		
			    		rivalesCubiertos[j]=rivalACubrir;
		    		}
		    		else{
		    			comandosDefensa.add(new ComandoIrA(j,
 			    				//alineacionEnCurso[j]
 			    				Posicion.media(
 			    						sp.rivales()[rivalesCubiertos[j]]
			    						,sp.balon()
			    						)
 			    				));
		    		}
		    		
        		}else{
            		// si yo tengo el balon, dejad de cubrir! estamos atacando! es mas importante el balon!
            		//comandosDefensa.add(new ComandoIrA(j,));
        			comandosDefensa.add(new ComandoIrA(j,
        					alineacionEnCurso[j]));
    				rivalesCubiertos[j]=-1;
            	}
		    }
	    		
    	}
    	
    	return comandosDefensa;
    }
    
    /*
    private List<Comando> getComandosMedia(SituacionPartido sp){
    	List<Comando> comandosMedia = new LinkedList<Comando>(); 
    	
    	//JugadorDetalle detalleMedio10 = sp.detalleMisJugadores()[0];
    	//while((detalleMedio10 = sp.detalleMisJugadores()[i++]).getNumero()!=10);
    	//Posicion medio10 = sp.misJugadores()[--i]; // en i queda el indice del jugador
    	Posicion[] medios = sp.misJugadores();
    	for(//Posicion medio: sp.misJugadores()
    		int j = 5; j < 9 ; j++
    		){
    		Posicion medio = medios[j];
		    	// si estas a menos de 15 del balon,
    			// ve a por el, pero solo hasta X de distancia de tu sitio
    		
    		if(
    				//jugadorTrasBalon != -1 &&
		    		medio.distancia(sp.balon())<15
		    		&& medio.distancia(alineacionEnCurso[j]) <= 30	
		    		){
    				comandosMedia.add(new ComandoIrA(j, sp.balon()));
		    		//jugadorTrasBalon = j;
		    	}
		    	// si no, vuelve a tu sitio --> mejor, a marcar a alg�n medio
    		else if(medio.distancia(alineacionEnCurso[j]) > 30){
    			rivalesCubiertos[j]=-1;
    			comandosMedia.add(new ComandoIrA(j,
		    				alineacionEnCurso[j]
		    				));
		    }else{
		    		if(rivalesCubiertos[j]==-1){
			    		int rivalACubrir = alineacionEnCurso[j]
			    		        .indiceMasCercano(sp.rivales(),
			    		        		rivalesCubiertos);
			    		comandosMedia.add(new ComandoIrA(j,
			    				//alineacionEnCurso[j]
			    				Posicion.media(
			    						sp.rivales()[rivalACubrir]
			    						,sp.balon()
			    						)
			    				)
			    		);
			    		
			    		rivalesCubiertos[j]=rivalACubrir;
		    		}
		    		else{
		    			comandosMedia.add(new ComandoIrA(j,
 			    				//alineacionEnCurso[j]
 			    				Posicion.media(
 			    						sp.rivales()[rivalesCubiertos[j]]
			    						,sp.balon()
			    						)
 			    				));
		    		}
		    	}
    	}
    	
    	return comandosMedia;
    }*/
    
    private double calcularAnguloTiro(double distancia) {
    	//double resultado = 180/Math.PI*Math.asin(Constantes.G * distancia / Math.pow(Constantes.REMATE_VELOCIDAD_MAX, 2))/2; 
    	////System.out.println(" para " + distancia + " sale " + resultado);
    	
    	double resultado = distancia; //60 - 2*distancia;//-distancia + 60; -- demasiado alto de cerca
    	/*(180/Math.PI)*1;
    	
    	(distancia, angulo) --> (x, y) --> (0, 90), (15, 60), (30, 30)
    	 //y = -x + 60 = 60 - x
    	 y = -2*distanca + 90
    	 */
    	 
		return resultado;
	}
    
    private double calcularPosicionTiro(Posicion rematador, double errorJugador) {
    	double resultado = Constantes.LARGO_ARCO/4*(rand.nextBoolean()?1:-1);
    	
    	Posicion palo1 = 
			Constantes.centroArcoSup
			.moverPosicion(Constantes.LARGO_ARCO/2, 0);
    	
    	Posicion palo2 = 
			Constantes.centroArcoSup
			.moverPosicion(-Constantes.LARGO_ARCO/2, 0);
    	
    	double distanciaPalo1 = rematador.distancia(
    			Constantes.centroArcoSup
    			.moverPosicion(Constantes.LARGO_ARCO/2, 0));
    	
    	double distanciaPalo2 = rematador.distancia(
    			Constantes.centroArcoSup
    			.moverPosicion(-Constantes.LARGO_ARCO/2, 0));
    	
    	// es el que limita el angulo maximo porque mete error en ambos lados de la linea teorica de tiro
    	Posicion paloCorto = distanciaPalo1 >= distanciaPalo2? palo2:palo1; // si estamos en el medio, tira a este lado mismo
    	Posicion paloLargo = distanciaPalo1 > distanciaPalo2? palo1:palo2;
    	
    	// angulo maximo de desviacion para que sea gol vaya a donde vaya el tiro
    	double anguloCorto = rematador.angulo(paloCorto);
    	double anguloLargo = rematador.angulo(paloLargo);
    	
    	double anguloCentro = rematador.angulo(Constantes.centroArcoSup);
    	double error = Constantes.getErrorAngular(errorJugador);// en grados!
    	
    	
    	
    	// mejor tirar SIEMPRE al palo CORTO (hay mas margen asumible de error para que sea gol
    	if((anguloCentro - anguloCorto) < error){ // no podemos fallar por el corto!
    		resultado = ((anguloCentro - anguloCorto) - error);
    	}else if (Math.abs(anguloCentro - anguloLargo) < error){ // no podemos fallar por el largo!
    		/*
    		 Esto no se podr�a dar, ya que el largo siempre es peor que el corto, no? 
    		 */
    		resultado = (anguloCentro - anguloLargo) - error;
    	}else{// ante no poder asegurar el tiro, por el medio
    		resultado = 0;
    	}
    	
    	/*
    	//System.out.println("angulo centro: " + anguloCentro);
    	//System.out.println("angulo corto: " + anguloCorto);
    	//System.out.println("angulo largo: " + anguloLargo);
    	//System.out.println("angulo error: " + error);
    	//System.out.println("angulo Math.abs(anguloCentro - anguloCorto): " + Math.abs(anguloCentro - anguloCorto));
    	//System.out.println("angulo Math.abs(anguloCentro - anguloLargo): " + Math.abs(anguloCentro - anguloLargo));
    	*/
    	
    	/*//System.out.println(rematador.distancia(Constantes.centroArcoInf)
    			//*Math.cos(180*(rematador.angulo(Constantes.centroArcoInf) - resultado)/Math.PI );
    			*Math.cos(rematador.angulo(Constantes.centroArcoInf) ));
    	*/
    	
		return 0;
	}

	private List<Comando> getComandosPortero(SituacionPartido sp){
    	List<Comando> comandosPortero = new LinkedList<Comando>(); 
    	
    	int i = 0;//iterador comun
    	int rematan[] = sp.puedenRematar();
    	
    	JugadorDetalle detallePortero = sp.detalleMisJugadores()[0];
    	while(!(detallePortero = sp.detalleMisJugadores()[i++]).esPortero());
    	Posicion portero = sp.misJugadores()[--i];// en i queda el indice del jugador
    	Posicion rivalMasCercanoAlBalon = sp.rivales()[sp.balon().indiceMasCercano(sp.rivales())];
    	// si el balon esta menos de 30 de la porteria, entonces ir a balon, si no
    		// siempre entre la porteria y el jugador contrario mas cercano
    	
    	// distancia max a la que se puede tirar sin que bote (30), pero sale demasiado
    	if(sp.balon().distancia(Constantes.centroArcoInf)< 20){
    		if (sp.alturaBalon() == 0) // si va a ras, vete a por el balon
    			comandosPortero.add(new ComandoIrA(i, sp.balon()));
    		else // vete a porteria //TODO buscar el siguiente bote del balon, para pararlo ahi!
    			comandosPortero.add(new ComandoIrA(i,
    					// acercate a la posicion X del balon en la porteria!
    						new Posicion(sp.balon().getX(), Constantes.centroArcoInf.getY()) 
    					//Constantes.centroArcoInf
    					/*Posicion.media(Constantes.centroArcoInf, 
    	    					sp.balon() // el medio entre balon y porteria? mejor vete a la porteria directo
    	    					 )*/
    					));
    	}
    	// si hay un rival cerca (del balon!!!), es potencialmente tirador
    	else if(rivalMasCercanoAlBalon.distancia(Constantes.centroArcoInf) < 10){
    		comandosPortero.add(new ComandoIrA(i,
    			Posicion.media(Constantes.centroArcoInf, 
    					rivalMasCercanoAlBalon
    					 )
    				)
    			);
		}
    	// si no hay peligro, vuelve a tu sitio, un poco mas adelantado (ganamos tiempo de respuesta)
    	else{
    		comandosPortero.add(new ComandoIrA(i,
    				// 7 parece equilibrado entre cortar al delantero y volver al tiro a puerta
	    				Constantes.centroArcoInf.moverPosicion(0, 7)
	    				)
	    			);
		}
    	
    	for(int rematador : rematan){
    		////System.out.println(rematador);
    		////System.out.println(sp.detalleMisJugadores()[rematador].getNumero());
    		
    		boolean pase = false;
    		/*int[] cercanos = sp.misJugadores()[i].indicesMasCercanos(sp.misJugadores());
    		
    		for (int j = 1; !pase && j < cercanos.length; j++) {
    			//System.out.println("pase a:" + j);
        		//System.out.println("pase a:" + sp.detalleMisJugadores()[j].getNumero());
    			comandos.add(new ComandoGolpearBalon(i, sp.misJugadores()[cercanos[j]], 1, true));
    			pase = true;
    		}*/
    		
    		// Patadon al centro (QUE LO BUSQUE UN MEDIO!!!!)
    		//comandosPortero.add(new ComandoGolpearBalon(i, Constantes.centroCampoJuego, 1, true));
    		addComandoGolpeo(comandosPortero,
    				new ComandoGolpearBalon(i, Constantes.centroCampoJuego, 1, true));
    	}
    	return comandosPortero;
    }
	
	private double calcularFuerzaLineal(double distancia){
		// la idea es que sea lineal 0 --> 0; 30 --> 1
		double resultado = distancia / 30;
		return resultado > 1?1:resultado;
	}
	
	private void addComandoGolpeo(List comandos, Comando comando){
		comandos.add(comando);
		//tengoYoElBalon = true; //TODO como se yo que ya no tengo el balon? como se que golpeo el? 
	}
}